%% Author: f355
%% Created: 31.01.2010
%% Description: TODO: Add description to ddc_process
-module(ddc_learn).

%%
%% Include files
%%
-include("ddc_settings.hrl").
-include("ddc_records.hrl").

%%
%% Exported Functions
%%
-compile(export_all).
-export([learn/2]).

%%
%% API Functions
%%

learn(Sentence, Mode) ->
    {Words, Phrases} = case ddc_learn:to_tuples(Sentence) of
			   {error, _, _} -> {[],[]};
			   {ok, W, Ph} -> {W, Ph}
		       end,
    ddc_db:run_query(fun() -> ddc_db:write(phrases, Phrases) end, Mode),
    ddc_db:run_query(fun() -> ddc_db:write(words, Words) end, Mode),
    ok.


%%
%% Local Functions
%%

%% to_tuples/1 - Turn original list of words into list of tuples like {Phrase, Word, Dir}.
%%				 Phrase is a list of words with length of CARDINALITY.
to_tuples(List) when length(List) > ?CARDINALITY-1 ->
    {Words, Phrases} = to_tuples([strstart|List]++[strend],[],[]),
    {ok, rollup(lists:usort(Words)), rollup(lists:usort(Phrases))};

to_tuples(List) ->
    {error, too_short, List}.

to_tuples([Word_b| Rest], Words, Phrases)
  when length([Word_b| Rest]) > ?CARDINALITY + 1 ->
    Phrase = lists:sublist(Rest, ?CARDINALITY),
    [Word_f| _] = lists:sublist(Rest, ?CARDINALITY + 1, 1),
    Phrases_b = #dir_tuple{key=Phrase, vals=Word_b, dir=b},
    Phrases_f = #dir_tuple{key=Phrase, vals=Word_f, dir=f},
    Words_b = if length(Word_f)<2 -> [];
		 Word_f=:=strstart -> [];
		 Word_f=:=strend -> [];
		 true -> [#dir_tuple{key=Word_f, vals=Phrase, dir=b}]
	      end,
    Words_f = if length(Word_b)<2 -> [];
		 Word_b=:=strstart -> [];
		 Word_b=:=strend -> [];
		 true -> [#dir_tuple{key=Word_b, vals=Phrase, dir=f}]
	      end,
    to_tuples(Rest, Words_f++Words_b++Words, [Phrases_f, Phrases_b| Phrases]);

to_tuples(_List, Words, Phrases) ->
    {Words, Phrases}.

rollup(List) ->
	rollup(List,void,[]).

rollup([H|T], Acc_tuple, Acc_res) when Acc_tuple#tuple.key=:=H#dir_tuple.key ->
    New_acc=case H#dir_tuple.dir of
		f -> Acc_tuple#tuple{vals_f=sets:add_element(H#dir_tuple.vals, Acc_tuple#tuple.vals_f)};
		b -> Acc_tuple#tuple{vals_b=sets:add_element(H#dir_tuple.vals, Acc_tuple#tuple.vals_b)}
	    end,
    rollup(T, New_acc, Acc_res);

rollup([], Acc_tuple, Acc_res) ->
    [Acc_tuple|Acc_res];

rollup([H|T], Acc_tuple, Acc_res) ->
    rollup(T,
	   case H#dir_tuple.dir of
	       f -> #tuple{key=H#dir_tuple.key, vals_f=sets:from_list([H#dir_tuple.vals]), vals_b=sets:new()};
	       b -> #tuple{key=H#dir_tuple.key, vals_f=sets:new(), vals_b=sets:from_list([H#dir_tuple.vals])}
	   end,
	   case Acc_tuple of
	       void -> Acc_res;
	       _ -> [Acc_tuple|Acc_res]
	   end
	  ).
